#include "lib/utils/ticker.h"
#include "lib/Utils/Square.h"
#include "lib/WindowsUtils/WinFile.h"

#include <iostream>
#include <vector>
#include <time.h>
#include <algorithm>

using namespace std;

void Visit(Square* a_Parent, Square* a_Who) {

	_ASSERT(!a_Parent->IsVisited());
	a_Parent->SetVisited(a_Who);

	vector<Square*> l_Neighbours = a_Parent->GetConnections();

	random_shuffle(l_Neighbours.begin(), l_Neighbours.end());

	while(l_Neighbours.size()) {
		Square* l_Curr = l_Neighbours.back();

		if(l_Curr) {
			if(l_Curr->IsVisited()) {
				a_Parent->RemoveLink(l_Curr);
			} else {
				Visit(l_Curr, a_Parent);
			}
		}

		l_Neighbours.pop_back();
	}
}

int main()
{
	//srand ( time(NULL) );
	srand ( 1 );

	const int l_GridSize = 5;
	Square* l_Squares[l_GridSize][l_GridSize];

	for(int i=0 ; i<l_GridSize ; i++) {
		for(int j=0 ; j<l_GridSize ; j++) {
			l_Squares[i][j] = new Square((l_GridSize*i) + j);
		}
	}

	for(int i=1 ; i<l_GridSize ; i++) {
		for(int j=0 ; j<l_GridSize ; j++) {
			l_Squares[i-1][j]->SetDown(l_Squares[i][j]);
			l_Squares[i][j]->SetUp(l_Squares[i-1][j]);
		}
	}

	for(int j=1 ; j<l_GridSize ; j++) {
		for(int i=0 ; i<l_GridSize ; i++) {
			l_Squares[i][j-1]->SetRight(l_Squares[i][j]);
			l_Squares[i][j]->SetLeft   (l_Squares[i][j-1]);
		}
	}

	vector<int> l_Edges;

	for(int i=0 ; i<l_GridSize ; i++) {
		for(int j=0 ; j<l_GridSize ; j++) {
			if(l_Squares[i][j]->IsEdgePiece()) {
				l_Edges.insert(l_Edges.end(), l_Squares[i][j]->GetId());
			}
		}
	}

	int l_End = l_Edges[rand() % l_Edges.size()];

	Square* l_Start = l_Squares[l_End/l_GridSize][l_End%l_GridSize];

	Visit(l_Start, 0);
    
	WinFile l_Maze = WinFile::OpenReadWrite("C:/Tmp/Maze.txt");

	const int l_Width = (l_GridSize*2)+1;
	char l_Grid[l_Width][l_Width];

	for(int i=0 ; i<l_Width ; i++) {
		for(int j=0 ; j<l_Width ; j++) {
			if(i%2 == 1 && j%2 == 1) {
				l_Grid[i][j] = 'o';
			} else {
				l_Grid[i][j] = '#';
			}
		}
	}

	for(int i=0 ; i<l_GridSize ; i++) {
		for(int j=0 ; j<l_GridSize ; j++) {
			const std::vector<Square*>& l_Connections = l_Squares[i][j]->GetConnections();

			if(l_Connections[SQC_UP] != 0) {
				l_Grid[((i*2)+2)][((j*2)+1)] = 'o';
			}

			if(l_Connections[SQC_RIGHT] != 0) {
				l_Grid[((i*2)+1)][((j*2)+2)] = 'o';
			}

			if(l_Connections[SQC_DOWN] != 0) {
				l_Grid[((i*2))][((j*2)+1)] = 'o';
			}

			if(l_Connections[SQC_LEFT] != 0) {
				l_Grid[((i*2)+1)][((j*2))] = 'o';
			}
		}
	}

	for(int i=0 ; i<l_Width ; i++) {
		l_Maze.Write(std::string(l_Grid[i], l_Width));
		l_Maze.Write("\r\n");
	}


	//for (int i=0 ; i<l_Total ; i++) {
	//	Square* l_Sq = new Square(i);
	//	l_array.insert(l_array.end(), l_Sq);

	//	if(i-l_GridSize > -1) {
	//		l_array.[i-l_GridSize]->SetDown(l_Sq);
	//		l_Sq->SetUp(l_array[i-l_GridSize]);
	//	}
	//}


	//double l_FrameRate = 60.0;
	//__int64 l_Freq = 1000.0 / l_FrameRate;

	//Ticker l_Ticker;

	//while(true) {
	//	if(l_Ticker.GetLapsed() >= l_Freq) {
	//		cout << l_Ticker.GetLapsed()/1000.0 << endl;
	//		l_Ticker.Reset();
	//	}
	//}

	return 0;
}